package org.tlang.ast.leaf;

import org.tlang.ast.ASTLeaf;
import org.tlang.metaclass.TSetter;
import org.tlang.context.*;
import org.tlang.exception.EvalException;
import org.tlang.exception.TypeException;
import org.tlang.lexer.token.Token;
import org.tlang.type.Type;

public class Name extends ASTLeaf implements TSetter {
    private int nest;
    private int index;

    public Name(Token token) {
        super(token);
        index = Location.UNKNOWN;
    }

    public String name() {
        return token.getText();
    }

    @Override
    public void lookup(SymbolTable symbolTable, TypeTable typeTable) {
        Location location = symbolTable.where(name());
        if (location == null) {
            throw new EvalException("undefined identifier: " + this, this);
        }

        nest = location.nest();
        index = location.index();
    }

    @Override
    public Object eval(ValueTable valueTable) {
        return valueTable.get(nest, index);
    }

    @Override
    public void set(ValueTable valueTable, Object value) {
        valueTable.update(nest, index, value);
    }

    @Override
    public Type typeCheck(TypeTable typeTable) throws TypeException {
        Type type = typeTable.get(nest, index);
        if (type == null) {
            throw new TypeException("undefined identifier: " + this, this);
        } else {
            return type;
        }
    }
}
